﻿function Install-SharePointPostPrereqOptionalSoftware
{
    <# 
     .Synopsis
        Installs optional software and updates for SharePoint that are not included in the SharePoint Prerequisite Installer

     .Description
        This script executes unattended installations for each of the optional software packages for SharePoint that are not included in the SharePoint Prerequisite installer. The script will detect the underlying OS Version and select the installers that are appropriate. The following software will be installed by this script:

        For SharePoint 2013
        
            Both Windows Server 2008 R2 SP1 and Windows Server 2012
                Optional Component 1:
                Workflow Client
                http://www.microsoft.com/en-us/download/details.aspx?id=35375
                http://download.microsoft.com/download/D/B/D/DBD439A9-370D-40EA-B3B7-45CD935B98FB/WF/WorkflowClient.exe
        
                Optional Component 2:
                Microsoft SQL Server 2012 Data-Tier Application (DAC) Framework 64-bit edition
                http://go.microsoft.com/fwlink/p/?LinkId=238829

                Optional Component 3:
                Microsoft SQL Server 2012 Transact-SQL ScriptDom 64-bit edition
                http://go.microsoft.com/fwlink/p/?LinkId=239635

                Optional Component 4:
                Microsoft System CLR Types for Microsoft SQL Server 2012 64-bit edition 
                http://go.microsoft.com/fwlink/p/?LinkId=239644

                Optional Component 5:
                Exchange Web Services Managed API, version 1.2 
                http://go.microsoft.com/fwlink/p/?linkid=238668

            Windows Server 2008 R2 SP1 Only
                Hotfix 1:
                You cannot customize some TCP configurations by using the netsh command in Windows Server 2008 R2
                http://support.microsoft.com/kb/2472264/en-us

        For SharePoint 2010
                <NOT CURRENTLY IMPLEMENTED>       

     .Parameter Ws2012InstallFiles
        The full file system path where the installation source files for the Windows Server 2012 hotfixes are located.
        The default value for this parameter is '$env:ProgramData\SharePoint Total Automation Toolkit\Software\03-OptionalPrereqs\WS2012'

     .Parameter W2K8R2Sp1InstallFiles
        The full file system path where the installation source files for the Windows Server 2008 R2 SP1 hotfixes are located.
        The default value for this parameter is '$env:ProgramData\SharePoint Total Automation Toolkit\Software\03-OptionalPrereqs\W2K8R2Sp1'

     .Parameter CommonInstallFiles
        The full file system path where the installation source files common to all target operating system hotfixes are located.
        The default value for this parameter is '$env:ProgramData\SharePoint Total Automation Toolkit\Software\03-OptionalPrereqs\Common'

     .Parameter SharePointVersion
        Use this parameter to indicate which SharePoint Version to install. Valid choices are '2010' and '2013'

     .Example
        Install-SharePointPostPrereqOptionalSoftware

        # If using the default file path and installing for SharePoint 2013

     .Example
        Install-SharePointPostPrereqOptionalSoftware -SharePointVersion 2013 -Ws2012InstallFiles 'C:\ProgramData\SharePoint Total Automation Toolkit\Software\03-OptionalPrereqs\WS2012' -W2K8R2Sp1InstallFiles 'C:\ProgramData\SharePoint Total Automation Toolkit\Software\03-OptionalPrereqs\W2K8R2Sp1'

        # If using a custom location for the installation files default configuration file path and structure, provide discrete paramaters to each subdirectory
    #>
    [CmdletBinding(DefaultParametersetName="CustomPaths")]
    param([parameter(ParameterSetName = "CustomPaths", 
                     Mandatory = $false,
                     HelpMessage = "The full file system path where the installation source files for the Windows Server 2012 hotfixes are located. The default value for this parameter is 'C:\ProgramData\SharePoint Total Automation Toolkit\Software\03-OptionalPrereqs\WS2012'")]
                     [string]$Ws2012InstallFiles = ($env:ProgramData + "\SharePoint Total Automation Toolkit\Software\03-OptionalPrereqs\WS2012"),
	      [parameter(ParameterSetName = "CustomPaths", 
                     Mandatory = $false,
                     HelpMessage = "The full file system path where the installation source files for the Windows Server 2008 R2 SP1 hotfixes are located. The default value for this parameter is 'C:\ProgramData\SharePoint Total Automation Toolkit\Software\03-OptionalPrereqs\W2K8R2Sp1'")]
                     [string]$W2K8R2Sp1InstallFiles = ($env:ProgramData + "\SharePoint Total Automation Toolkit\Software\03-OptionalPrereqs\W2K8R2Sp1"),
	      [parameter(ParameterSetName = "CustomPaths", 
                     Mandatory = $false,
                     HelpMessage = "The full file system path where the installation source files common to all target operating system hotfixes are located. The default value for this parameter is 'C:\ProgramData\SharePoint Total Automation Toolkit\Software\03-OptionalPrereqs\Common'")]
                     [string]$CommonInstallFiles = ($env:ProgramData + "\SharePoint Total Automation Toolkit\Software\03-OptionalPrereqs\Common"),
          [parameter(ParameterSetName = "CustomPaths",
                     Mandatory = $false,
                     HelpMessage = "Use this parameter to indicate which SharePoint Version to install. Valid choices are '2010' and '2013'")]
                     [ValidateSet ("2010","2013")]
                     [string]$SharePointVersion = "2013",
          [parameter(ParameterSetName = "CustomPaths",
                     Mandatory = $false,
                     HelpMessage = "The full file system path where the offline cache of installation source files for Workflow Manager are located. The default value for this parameter is 'C:\ProgramData\SharePoint Total Automation Toolkit\Software\13-Workflow\feeds\latest\webproductlist.xml'")]
                     [string]$WorkflowInstallFiles = ($env:ProgramData + "\SharePoint Total Automation Toolkit\Software\13-Workflow"),
          [parameter(ParameterSetName = "CustomPaths",
                     Mandatory = $false,
                     HelpMessage = "The full file system path where the offline cache of installation source files for Workflow Manager are located. The default value for this parameter is 'C:\ProgramData\SharePoint Total Automation Toolkit\Software\13-Workflow\feeds\latest\webproductlist.xml'")]
                     [string]$WebPiProductListXmlFile = ($env:ProgramData + "\SharePoint Total Automation Toolkit\Software\13-Workflow\feeds\latest\webproductlist.xml"))

    switch ($PSCmdlet.ParameterSetName)
    {
        "CustomPaths"
        {
        }    
    }

	$rebootStatus = Get-PendingReboot
	if ($rebootStatus.RebootPending -eq $true)
	{
		Write-Host "NOTE: A system restart is required. Please restart the system prior to continuing with the installation." -ForegroundColor Yellow
		Write-Host "      When the system restarts please rerun this script until you no longer receive a restart request." -ForegroundColor Yellow
		throw 
	}

    # Initialize Progress Variables
    [int]$progressNumPhases = 2
    [int]$progressNumPhasesComplete = 0
    [int]$progressCurrentTask = 0
    [int]$progressTotalTasks = 0
    [int]$progressTotal = 0
    [int]$progressBarId = 100
    $startTime = [System.DateTime]::Now

    Write-Host
    Write-Host "Beginning the SharePoint Post Prerequisite Optional Software Installation."

    # First determine which OS we are installing on
    $osVersionMajor = [System.Environment]::OSVersion.Version.Major
    $osVersionMinor = [System.Environment]::OSVersion.Version.Minor

    If ($SharePointVersion -eq "2013")
    {
        # If we are installing on Windows Server 2012
        if (($osVersionMajor -eq 6) -and ($osVersionMinor -eq 2))
        {    
            # Platform specific installs go here
        }
        # If we are installing on Windows Server 2008 R2
        elseif (($osVersionMajor -eq 6) -and ($osVersionMinor -eq 1))
        {
		    # Initialize the progress variables for the current phase
		    $progressCurrentTask = 0
		    $progressTotalTasks = 1

            #region Task 1

            # Hotfix 1:
            # You cannot customize some TCP configurations by using the netsh command in Windows Server 2008 R2
            # http://support.microsoft.com/kb/2472264/en-us
            $hotfixFile = "Windows6.1-KB2472264-v3-x64.msu"
            $setupExe = "wusa.exe"
            $setupArgs = ('"' + $W2K8R2Sp1InstallFiles + '\' + $hotfixFile + '"') + ' /quiet /norestart'

            $setupExeInstance = [System.Diagnostics.Process]::Start($setupExe, $setupArgs)

            while (-not ($setupExeInstance.HasExited)){
                $currentRuntime = [System.DateTime]::Now - $startTime
                Write-Progress -Id $progressBarId -Activity "Installing SharePoint Post Prerequisite Optional Software" -PercentComplete $progressTotal -CurrentOperation ("Installing hotfix - " + $hotfixFile) -Status ("The current operation has been running for {0}:{1}:{2}" -f $currentRuntime.Hours.ToString("00"), $currentRuntime.Minutes.ToString("00"), $currentRuntime.Seconds.ToString("00"))

                Start-Sleep -Seconds 1
            }

            if ($setupExeInstance.ExitCode -eq 0)
            {
                Write-Host "     Hotfix successfully installed ($hotfixFile)"        
            }
            else 
            {
                Write-Error "     Installation of hotfix ($hotfixFile) failed"
                throw
            }

		    # Increment the progress variables for the current task
		    $progressCurrentTask++
		    $progressTotal = CalculateProgress $progressCurrentTask $progressTotalTasks $progressNumPhases $progressNumPhasesComplete
        
            #endregion
        }

        # Increment the Phase Completion Counter
        $progressNumPhasesComplete++

        # Install components that are common between Server 2012, Server 2012 R2, and Server 2008 R2
        if ((($osVersionMajor -eq 6) -and ($osVersionMinor -eq 2)) -or (($osVersionMajor -eq 6) -and ($osVersionMinor -eq 3)) -or ((($osVersionMajor -eq 6) -and ($osVersionMinor -eq 1))))
        {    
		    # Initialize the progress variables for the current phase
		    $progressCurrentTask = 0
		    $progressTotalTasks = 5

            #region Task 1

            # Optional Component 1:
            # Workflow Client
            # http://www.microsoft.com/en-us/download/details.aspx?id=35375
            # http://download.microsoft.com/download/D/B/D/DBD439A9-370D-40EA-B3B7-45CD935B98FB/WF/WorkflowClient.exe
            $hotfixFile = "WebPICMD.exe"
            $setupExe = ('"' + $WorkflowInstallFiles + '\Bin\' + $hotfixFile + '"')
            $setupArgs = ('/Install /AcceptEULA /SuppressReboot /Products:"WorkflowClient" /XML:"{0}"' -f $WebPiProductListXmlFile)
            $setupExeInstance = [System.Diagnostics.Process]::Start($setupExe, $setupArgs)
            
            while (-not ($setupExeInstance.HasExited)){
                $currentRuntime = [System.DateTime]::Now - $startTime
                Write-Progress -Id $progressBarId -Activity "Installing SharePoint Post Prerequisite Optional Software" -PercentComplete $progressTotal -CurrentOperation ("Installing hotfix - " + $hotfixFile) -Status ("The current operation has been running for {0}:{1}:{2}" -f $currentRuntime.Hours.ToString("00"), $currentRuntime.Minutes.ToString("00"), $currentRuntime.Seconds.ToString("00"))

                Start-Sleep -Seconds 1
            }

            if ($setupExeInstance.ExitCode -eq 0)
            {
                Write-Host "     Optional component successfully installed ($hotfixFile)"        
            }
            else 
            {
                Write-Error "     Installation of optional component ($hotfixFile) failed"
                throw
            }

		    # Increment the progress variables for the current task
		    $progressCurrentTask++
		    $progressTotal = CalculateProgress $progressCurrentTask $progressTotalTasks $progressNumPhases $progressNumPhasesComplete
        
            #endregion

            #region Task 2

            # Optional Component 2:
            # Microsoft SQL Server 2012 Data-Tier Application (DAC) Framework 64-bit edition
            # http://go.microsoft.com/fwlink/p/?LinkId=238829
            $hotfixFile = "dacframework.msi"
            $setupExe = "msiexec.exe"
            $setupArgs = '/qn /i ' + ('"' + $CommonInstallFiles + '\' + $hotfixFile + '"')

            $setupExeInstance = [System.Diagnostics.Process]::Start($setupExe, $setupArgs)

            while (-not ($setupExeInstance.HasExited)){
                $currentRuntime = [System.DateTime]::Now - $startTime
                Write-Progress -Id $progressBarId -Activity "Installing SharePoint Post Prerequisite Optional Software" -PercentComplete $progressTotal -CurrentOperation ("Installing hotfix - " + $hotfixFile) -Status ("The current operation has been running for {0}:{1}:{2}" -f $currentRuntime.Hours.ToString("00"), $currentRuntime.Minutes.ToString("00"), $currentRuntime.Seconds.ToString("00"))

                Start-Sleep -Seconds 1
            }

            if ($setupExeInstance.ExitCode -eq 0)
            {
                Write-Host "     Optional component successfully installed ($hotfixFile)"        
            }
            else 
            {
                Write-Error "     Installation of optional component ($hotfixFile) failed"
                throw
            }

		    # Increment the progress variables for the current task
		    $progressCurrentTask++
		    $progressTotal = CalculateProgress $progressCurrentTask $progressTotalTasks $progressNumPhases $progressNumPhasesComplete
        
            #endregion

            #region Task 3

            # Optional Component 3:
            # Microsoft SQL Server 2012 Transact-SQL ScriptDom 64-bit edition
            # http://go.microsoft.com/fwlink/p/?LinkId=239635
            $hotfixFile = "SQLDOM.msi"
            $setupExe = "msiexec.exe"
            $setupArgs = '/qn /i ' + ('"' + $CommonInstallFiles + '\' + $hotfixFile + '"')

            $setupExeInstance = [System.Diagnostics.Process]::Start($setupExe, $setupArgs)

            while (-not ($setupExeInstance.HasExited)){
                $currentRuntime = [System.DateTime]::Now - $startTime
                Write-Progress -Id $progressBarId -Activity "Installing SharePoint Post Prerequisite Optional Software" -PercentComplete $progressTotal -CurrentOperation ("Installing hotfix - " + $hotfixFile) -Status ("The current operation has been running for {0}:{1}:{2}" -f $currentRuntime.Hours.ToString("00"), $currentRuntime.Minutes.ToString("00"), $currentRuntime.Seconds.ToString("00"))

                Start-Sleep -Seconds 1
            }

            if ($setupExeInstance.ExitCode -eq 0)
            {
                Write-Host "     Optional component successfully installed ($hotfixFile)"        
            }
            else 
            {
                Write-Error "     Installation of optional component ($hotfixFile) failed"
                throw
            }

		    # Increment the progress variables for the current task
		    $progressCurrentTask++
		    $progressTotal = CalculateProgress $progressCurrentTask $progressTotalTasks $progressNumPhases $progressNumPhasesComplete
        
            #endregion

            #region Task 4

            # Optional Component 4:
            # Microsoft System CLR Types for Microsoft SQL Server 2012 64-bit edition 
            # http://go.microsoft.com/fwlink/p/?LinkId=239644
            $hotfixFile = "SQLSysClrTypes.msi"
            $setupExe = "msiexec.exe"
            $setupArgs = '/qn /i ' + ('"' + $CommonInstallFiles + '\' + $hotfixFile + '"')

            $setupExeInstance = [System.Diagnostics.Process]::Start($setupExe, $setupArgs)

            while (-not ($setupExeInstance.HasExited)){
                $currentRuntime = [System.DateTime]::Now - $startTime
                Write-Progress -Id $progressBarId -Activity "Installing SharePoint Post Prerequisite Optional Software" -PercentComplete $progressTotal -CurrentOperation ("Installing hotfix - " + $hotfixFile) -Status ("The current operation has been running for {0}:{1}:{2}" -f $currentRuntime.Hours.ToString("00"), $currentRuntime.Minutes.ToString("00"), $currentRuntime.Seconds.ToString("00"))

                Start-Sleep -Seconds 1
            }

            if ($setupExeInstance.ExitCode -eq 0)
            {
                Write-Host "     Optional component successfully installed ($hotfixFile)"        
            }
            else 
            {
                Write-Error "     Installation of optional component ($hotfixFile) failed"
                throw
            }

		    # Increment the progress variables for the current task
		    $progressCurrentTask++
		    $progressTotal = CalculateProgress $progressCurrentTask $progressTotalTasks $progressNumPhases $progressNumPhasesComplete
        
            #endregion

            #region Task 5

            # Optional Component 5:
            # Exchange Web Services Managed API, version 1.2 
            # http://go.microsoft.com/fwlink/p/?linkid=238668
            $hotfixFile = "EwsManagedApi.msi"
            $setupExe = "msiexec.exe"
            $setupArgs = '/qn /i ' + ('"' + $CommonInstallFiles + '\' + $hotfixFile + '"')

            $setupExeInstance = [System.Diagnostics.Process]::Start($setupExe, $setupArgs)

            while (-not ($setupExeInstance.HasExited)){
                $currentRuntime = [System.DateTime]::Now - $startTime
                Write-Progress -Id $progressBarId -Activity "Installing SharePoint Post Prerequisite Optional Software" -PercentComplete $progressTotal -CurrentOperation ("Installing hotfix - " + $hotfixFile) -Status ("The current operation has been running for {0}:{1}:{2}" -f $currentRuntime.Hours.ToString("00"), $currentRuntime.Minutes.ToString("00"), $currentRuntime.Seconds.ToString("00"))

                Start-Sleep -Seconds 1
            }

            if ($setupExeInstance.ExitCode -eq 0)
            {
                Write-Host "     Optional component successfully installed ($hotfixFile)"        
            }
            else 
            {
                Write-Error "     Installation of optional component ($hotfixFile) failed"
                throw
            }

		    # Increment the progress variables for the current task
		    $progressCurrentTask++
		    $progressTotal = CalculateProgress $progressCurrentTask $progressTotalTasks $progressNumPhases $progressNumPhasesComplete
        
            #endregion
        }

        # Increment the Phase Completion Counter
        $progressNumPhasesComplete++

        Write-Progress -Id $progressBarId -Activity "Installing SharePoint Post Prerequisite Optional Software" -Status "Finishing" -PercentComplete 100 -CurrentOperation "" -Completed

        Write-Host "SharePoint Post Prerequisite Optional Software Installation Complete."

    }
    elseif ($SharePointVersion -eq "2010")
    {
        throw "SharePoint 2010 updates have not yet been implemented. Please manually install any required hotfixes."
    }
}